package com.syqc.monitor.ui.historyline

import android.view.View
import android.widget.AdapterView
import android.widget.SeekBar
import android.util.LruCache
import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.BitmapDescriptor
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.LatLngBounds
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.Polyline
import com.amap.api.maps.model.PolylineOptions
import androidx.core.graphics.toColorInt
import com.syqc.maps.utils.MapUtil
import com.syqc.base.BaseMapFragment
import com.syqc.comlib.AppConfigs
import com.syqc.comlib.rx.filterFast
import com.syqc.comlib.utils.CacheMMKV
import com.syqc.comlib.utils.Language
import com.syqc.entity.HistoryLine
import com.syqc.interfaces.SimpleSeekBarChangeListener
import com.syqc.maps.movepoint.MovePointListener
import com.syqc.maps.movepoint.MovePointOverlay
import com.syqc.maps.movepoint.MovePointUtil
import com.syqc.maps.utils.StopMarker
import com.syqc.monitor.R
import com.syqc.monitor.color.ColorsPopup
import com.syqc.monitor.databinding.FragmentMapLine2Binding
import com.syqc.monitor.popup.MapTypePopup
import com.syqc.utils.ToolsUtil
import com.syqc.utils.Units

/** @Author Jasper @Time 2020/8/11 @Desc 历史轨迹碎片 */
class MapLineFragment : BaseMapFragment<FragmentMapLine2Binding>(FragmentMapLine2Binding::inflate) {
    private var pointOverlay: MovePointOverlay? = null
    private var addPolyline: Polyline? = null
    private var isShowTotal = true
    private val mAllPoints = ArrayList<LatLng>()

    //是否停止移动
    private var isStop = false

    //起点里程
    private var firstMile = 0f

    private var isFinish = false

    private var countEntity: HistoryLine.CountData? = null
    private var mLocations: List<HistoryLine.Location>? = null
    private var stopData: List<HistoryLine.StopData>? = null

    private val mMapPopup by lazy {
        MapTypePopup(requireContext()) {
            mMap?.mapType = if (it) {
                AMap.MAP_TYPE_NORMAL
            } else {
                AMap.MAP_TYPE_SATELLITE
            }
        }
    }

    //线条颜色
    var lineColor: String
        get() = CacheMMKV.decodeString("line_color", "#6C736B")
        set(value) {
            CacheMMKV.encode("line_color", value)
        }

    //播放速度
    private var seekProgress: Int = 5

    private val moveOptions: PolylineOptions by lazy {
        PolylineOptions().width(lineWidth).color(lineColor.toColorInt())
    }
    private var movePolyline: Polyline? = null
    private var lineWidth: Float = 20f
    private val mActivityVM by activityViewModels<LineInfoViewModel>()

    override fun initView(view: View) {
        seekProgress = CacheMMKV.decodeInt("line_speed", 20)
        binding.tvWidth1.isSelected = true
        mMap?.run {
            MapUtil.initMapSetting(this)
            setOnMarkerClickListener { true }
            pointOverlay = MovePointOverlay(
                this, BitmapDescriptorFactory.fromResource(R.mipmap.ic_marker_move)
            )

        }
        binding.cbAllData.isSelected = true
        binding.tvStartPoint.isSelected = Language.isEnglish()
        binding.tvEndPoint.isSelected = Language.isEnglish()
        binding.ivLineColor.setBackgroundColor(lineColor.toColorInt())
        binding.tvLineStop.isSelected = true
    }

    override fun initData() {
        mActivityVM.data.observe(this) {
            countEntity = it.countData
            mLocations = it.locations
            stopData = it.stopData
            binding.ivLineColor.postDelayed({
                initView(it)
                stopData?.let { data ->
                    initStopData(data)
                }
            }, 300)
        }

    }

    /** 暂停播放 */
    fun stopMove() {
        isStop = true
        pointOverlay?.pauseMove()
        binding.ivLinePlayPause.setImageResource(R.mipmap.ic_line_pause)
    }

    //是否显示当前位置信息
    private var isShowInfo = AppConfigs.isMapInfoOpen

    override fun initEvent() {
        //详情
        binding.tvLineInfo.setOnClickListener {
            isShowInfo = true
            binding.llPointInfo.isVisible = true
            binding.ivLineClose.isVisible = true
            initPointView(mLocations!![binding.linePointSeekBar.progress])
        }

        binding.ivLineClose.setOnClickListener {
            isShowInfo = false
            binding.llPointInfo.isVisible = false
            binding.ivLineClose.isVisible = false
        }
        binding.ivInfoClose.setOnClickListener {
            isShowInfo = false
            binding.llPointInfo.isVisible = false
            binding.ivLineClose.isVisible = false
        }

        //播放暂停
        binding.ivLinePlayPause.filterFast {
            if (isFinish) {
                isFinish = false
                moveOptions.points.clear()
                movePolyline?.options = moveOptions
            }
            isShowTotal = false
            binding.llTotalData.isVisible = false
            binding.llStartEnd.isVisible = false
            binding.llLineSetting.isVisible = false
            binding.cbAllData.isSelected = false
            pointOverlay?.startPause()
            isStop = false
        }

        //停止
        binding.ivLineStop.filterFast {
            isStop = true
            binding.linePointSeekBar.progress = 0
            if (binding.llPointInfo.isVisible) initPointView(mLocations!![0])
            pointOverlay?.reset()
            movePolyline?.remove()
            movePolyline = null
        }

        //设置
        binding.cbLineSetting.filterFast {
            binding.llLineSetting.isVisible = !binding.llLineSetting.isVisible
            binding.cbAllData.isVisible = !binding.llLineSetting.isVisible
        }

        binding.cbAllData.setOnClickListener {
            isShowTotal = !isShowTotal
            binding.llTotalData.isVisible = isShowTotal
            binding.llStartEnd.isVisible = isShowTotal
            binding.cbAllData.isSelected = isShowTotal
        }

        binding.ivLineColor.filterFast {
            changeColor()
        }

        //放大
        binding.ivMapZoomIn.setOnClickListener {
            mMap?.animateCamera(CameraUpdateFactory.zoomOut(), 600, null)
        }

        //缩小
        binding.ivMapZoomOut.setOnClickListener {
            mMap?.animateCamera(CameraUpdateFactory.zoomIn(), 600, null)
        }

        //地图标准\卫星设置
        binding.ivMapState.setOnClickListener {
            mMapPopup.showView(binding.ivMapState, mMap?.mapType == AMap.MAP_TYPE_NORMAL)

        }
        binding.speedSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                when (position) {
                    0 -> {
                        seekProgress = 5
                    }

                    1 -> {
                        seekProgress = 20
                    }

                    2 -> {
                        seekProgress = 50
                    }

                    3 -> {
                        seekProgress = 200
                    }

                    4 -> {
                        seekProgress = 600
                    }

                }
                MovePointUtil.setSpeed(seekProgress)
                CacheMMKV.encode("line_speed", seekProgress)
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {

            }
        }

        binding.tvWidth1.filterFast {
            lineWidth = 20f
            movePolyline?.width = lineWidth
            addPolyline?.width = lineWidth
            binding.tvWidth1.isSelected = true
            binding.tvWidth2.isSelected = false
            binding.tvWidth3.isSelected = false
        }
        binding.tvWidth2.filterFast {
            lineWidth = 28f
            movePolyline?.width = lineWidth
            addPolyline?.width = lineWidth
            binding.tvWidth1.isSelected = false
            binding.tvWidth2.isSelected = true
            binding.tvWidth3.isSelected = false
        }

        binding.tvWidth3.filterFast {
            lineWidth = 36f
            movePolyline?.width = lineWidth
            addPolyline?.width = lineWidth
            binding.tvWidth1.isSelected = false
            binding.tvWidth2.isSelected = false
            binding.tvWidth3.isSelected = true
        }



        pointOverlay?.setMovePointListener(object : MovePointListener {
            override fun current(index: Int, fromPoint: LatLng, toPoint: LatLng) {
                requireActivity().runOnUiThread {
                    binding.linePointSeekBar.progress = index
                    if (isShowInfo) initPointView(mLocations!![index])
                }
                mMap?.let {
                    //计算是否在屏幕内
                    val latLngBounds = it.projection.visibleRegion.latLngBounds
                    if (!latLngBounds.contains(toPoint)) {
                        it.animateCamera(CameraUpdateFactory.newLatLng(toPoint))
                    }
                }
            }

            override fun moving(latLng: LatLng) {
                if (isStop) return
                if (movePolyline == null) {
                    moveOptions.points = arrayListOf(latLng)
                    movePolyline = mMap?.addPolyline(moveOptions)
                    movePolyline?.color = lineColor.toColorInt()
                    MapUtil.showMapLatLng(mMap!!, latLng)
                } else {
                    moveOptions.add(latLng)
                    movePolyline?.options = moveOptions
                }
            }


            override fun startPause(isStart: Boolean) {
                requireActivity().runOnUiThread {
                    if (isStart) {
                        binding.ivLinePlayPause.setImageResource(R.mipmap.ic_line_play)
                    } else {
                        isStop = true
                        binding.ivLinePlayPause.setImageResource(R.mipmap.ic_line_pause)
                    }
                }
            }

            override fun finish() {
                isFinish = true
                isStop = true
                requireActivity().runOnUiThread {
                    binding.ivLinePlayPause.setImageResource(R.mipmap.ic_line_pause)
                }
            }
        })

        binding.tvLineStop.filterFast {
            binding.tvLineStop.isSelected = !binding.tvLineStop.isSelected
            if (binding.tvLineStop.isSelected) {
                stopData?.let {
                    initStopData(it)
                }
            } else {
                markers.forEach {
                    it.remove()
                }
                markers.clear()
            }

        }
    }


    /** 初始化View */
    fun initView(entity: HistoryLine) {

        val list: List<HistoryLine.Location> = entity.locations
        firstMile = list.first().mile.toFloat()
        for (item in entity.locations) {
            item.dmile = ToolsUtil.formitNumberD("2", item.mile.toFloat() - firstMile).toString()
            mAllPoints.add(LatLng(item.glat.toDouble(), item.glng.toDouble()))
        }
        pointOverlay?.setPoints(mAllPoints)

        binding.linePointSeekBar.max = mAllPoints.size - 1
        binding.linePointSeekBar.setOnSeekBarChangeListener(object : SimpleSeekBarChangeListener {
            override fun onStopTrackingTouch(seekBar: SeekBar?) {
                super.onStopTrackingTouch(seekBar)
                seekBar?.run {
                    pointOverlay?.change(progress)
                    initPointView(mLocations!![progress])
                    if (movePolyline == null) {
                        moveOptions.points = mAllPoints.subList(0, progress)
                        movePolyline = mMap?.addPolyline(moveOptions)
                        MapUtil.showMapLatLng(mMap!!, mAllPoints[progress])
                    } else {
                        moveOptions.points.clear()
                        MapUtil.showMapLatLng(mMap!!, mAllPoints[progress])
                        moveOptions.points = mAllPoints.subList(0, progress)
                        movePolyline?.options = moveOptions
                    }
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
                super.onStartTrackingTouch(seekBar)
                pointOverlay?.seekbarMove()

            }
        })

        val startPoint = list.first()
        val endPoint = list.last()
        //开始点
        MapUtil.addMarker(
            mMap!!,
            LatLng(startPoint.glat.toDouble(), startPoint.glng.toDouble()),
            if (Language.isEnglish()) R.mipmap.ic_marker_start_e else R.mipmap.ic_marker_start
        )
        //结束点
        MapUtil.addMarker(
            mMap!!,
            LatLng(endPoint.glat.toDouble(), endPoint.glng.toDouble()),
            if (Language.isEnglish()) R.mipmap.ic_marker_end_e else R.mipmap.ic_marker_end
        )
        binding.tvStartPoint.text = startPoint.addr
        binding.tvEndPoint.text = endPoint.addr
        binding.tvStartEndTime.text =
            "${getString(R.string.desc_start_end_time)}：${startPoint.time}~${endPoint.time}"
        initPoints()
        initRecycler()
    }

    /** 初始化Point */
    private fun initPoints() {
        setPolyLine()?.let {
            //移动到中心点
            MapUtil.showMapBounds(mMap!!, it)
        }

        if (mAllPoints.isEmpty()) {
            return
        }
        //画线 有需要可以参照其它画线功能添加图片
        val polylineOptions = PolylineOptions()
        polylineOptions.points = mAllPoints
        polylineOptions.width(lineWidth).customTexture =
            BitmapDescriptorFactory.fromResource(R.mipmap.ic_line_custtexture)
        polylineOptions.isDottedLine = true
        addPolyline = mMap?.addPolyline(polylineOptions)
        //是否展开定位信息弹窗
        if (AppConfigs.isLineInfoOpen) {
            binding.llPointInfo.isVisible = true
            binding.ivLineClose.isVisible = true
            isShowInfo = true
            initPointView(mLocations!![binding.linePointSeekBar.progress])
        }
    }

    private fun initPointView(entity: HistoryLine.Location) {
        binding.lrTvPointTime.setRightText(entity.time)
        binding.lrTvPointSpeed.setRightText("${entity.speed} ${Units.speed} , ${entity.drctCn}")

        binding.lrTvPointMile.setRightText("${entity.dmile} ${Units.km}")
        binding.tvPointAddress.text = entity.addr
    }

    ////////////////////////////////////////整体数据//////////////////////////////////////////////
    private fun initRecycler() {
        val list: HistoryLine.CountData = countEntity!!
        binding.lrTvSpeedTime.setRightText(list.moveLong)
        binding.lrTvSpeedMax.setRightText("${list.maxSpeed} ${Units.speed}")
        binding.lrTvStopTime.setRightText(list.stopLong)
        binding.lrTvStopAverage.setRightText("${list.avgSpeed} ${Units.speed}")
        binding.lrTvRunMile.setRightText("${list.mile} ${Units.km}")
        binding.lrTvLocationNum.setRightText("${list.gpsSize} ${getString(R.string.desc_unit_num)}")
        val nullOrEmpty = list.totalLong == null
        binding.llTimeAvg.isVisible = !nullOrEmpty
        if (nullOrEmpty) return
        binding.lrTvTimeTotal.setRightText(list.totalLong ?: "")
        binding.lrTvRunAvg.setRightText("${list.avgMove} ${Units.speed}")
    }

    private val mPopup by lazy {
        ColorsPopup(
            requireContext(), R.string.dialog_choose_line_color, colorCallback
        )
    }
    private val colorCallback = object : ColorsPopup.Callback {
        override fun callback(index: Int, color: String) {
            lineColor = color
            binding.ivLineColor.setBackgroundColor(color.toColorInt())
            movePolyline?.color = color.toColorInt()
        }

    }

    private fun changeColor() {
        mPopup.showPopup(requireActivity().window.decorView, lineColor)
    }

    /** 设置轨迹线 */
    private fun setPolyLine(): LatLngBounds? {
        mLocations?.run {
            mAllPoints.clear();
            val bounds = LatLngBounds.builder()
            for (location in this) {
                val latLng = LatLng(location.glat.toDouble(), location.glng.toDouble())
                mAllPoints.add(latLng)
                bounds.include(latLng)
            }
            return bounds.build()
        }
        return null
    }

    override fun onDestroy() {
        super.onDestroy()
        pointOverlay?.destroy()
        pointOverlay = null
        lruCache.evictAll()
    }

    //    /**********************************************************************************
    private val stopList = ArrayList<LatLng>()
    private val markers = mutableListOf<Marker>()

    /**
     * 设置停止点数据
     *android 怎么修改自定义系统字体
     */
    private fun initStopData(list: List<HistoryLine.StopData>) {
        markers.forEach {
            it.remove()
        }
        markers.clear()
        list.forEachIndexed { index, stopData ->
            val latLng = LatLng(stopData.glat.toDouble(), stopData.glng.toDouble())
            stopList.add(latLng)
            val position = index + 1
            var bitmapDescriptor = lruCache.get(position)
            if (bitmapDescriptor == null) {
                val markerView = StopMarker(requireContext(), position)
                bitmapDescriptor = BitmapDescriptorFactory.fromView(markerView)
                lruCache.put(position, bitmapDescriptor)
            }
            val marker = MapUtil.addTagMarker(mMap!!, latLng, bitmapDescriptor!!, position)
            markers.add(marker)
        }
    }

    val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
    private var lruCache = object : LruCache<Int, BitmapDescriptor?>(maxMemory) {
        override fun entryRemoved(
            evicted: Boolean,
            key: Int,
            oldValue: BitmapDescriptor?,
            newValue: BitmapDescriptor?
        ) {
            super.entryRemoved(evicted, key, oldValue, newValue)
            oldValue?.recycle()
        }
    }
}